#ifndef PACKET_HEADERS_H
#define PACKET_HEADERS_H

#include "Includes.h"

#define MAX_MESSAGE_SIZE 2048


#define UNAME_LEN 32
#define GAMENAME_LEN 128

// This is included at the front of every packet sent
struct global_header {
	uint16_t mess_size; //including all headers
	uint16_t mess_type;
} __attribute__((packed)); //TODO: All this packing is not platform independent; we need to figure out how to do that




//Sent from client to server to join the server
#define MT_LOGIN_REQ 0xAA00 //All these definitions which begin with MT_ are the message type
struct login_request {
	uint8_t username[UNAME_LEN]; //Ends with a null terminator: '\0'
} __attribute__((packed));

#define MT_LOGIN_REFUSE 0xAA01
struct login_refuse {
	uint16_t reason;
} __attribute__((packed));
#define LR_USERNAME_TAKEN 0x0000
#define LR_BANNED 0x0001
#define LR_SERVER_FULL 0x0002




//Gets round trip time
#define MT_PROBE_REQUEST 0xAB00
struct probe_request {
	uint64_t curr_sys_time_micro;
} __attribute__((packed));

#define MT_PROBE_RESPONSE 0xAB01
struct probe_response {
	uint64_t time_from_req;
} __attribute__((packed));





struct player_data {
	uint8_t username[UNAME_LEN];
	uint8_t ip[16]; //If it's ipv4 only bytes 0-3 are used- the rest are zeros
	uint32_t ping; //Round trip time in microseconds from the server
	uint8_t status; //1 for idle, 2 for playing
	uint32_t player_id; //unique id for easy lookup
	
} __attribute__((packed));

struct game_data {
	uint8_t game_instance_name[128]; //You can name the game "John join this" or something- is this what "name" is supposed to be?
	uint8_t game_app_name[128]; //eg "Super Smash Bros"
	uint8_t hosting_player[UNAME_LEN]; //perhaps we should include a full list of struct player_data members?
	uint32_t game_id; //unique id for easy lookup
	uint32_t game_hash; //hash the rom and make sure it's actually the same game and not just the same name; not sure if this is necessary or not
	uint8_t num_players;
	uint8_t max_players;
	uint8_t status; //0- waiting; 1- netsync; 2- playing
} __attribute__((packed));
// num_player player_id's that are in the game follow this as a payload


#define MT_USERS_JOINED_SERVER 0xAC00
struct users_joined_server {
	uint32_t num_players;
} __attribute__((packed));
//The payload is a series of struct player_data; send a list of these on joining the server, and sends one of them every time someone new joins.

#define MT_USER_LEFT_SERVER 0xAC01
struct user_left_server {
	uint32_t player_id;
} __attribute__((packed));



//Tells a client to add these game(s) to its list
#define MT_ADD_GAME 0xAD00
struct add_game {
	uint32_t num_games;
} __attribute__((packed));
//The payload is a series of struct player_data; send a list of these on joining the server, and sends one of them every time someone new joins.

//tells a client to remove this game from its list
#define MT_REMOVE_GAME 0xAD01
struct remove_game {
	uint32_t game_id;
} __attribute__((packed));

//Tells a client to update the following data on this game
#define MT_UPDATE_GAME 0xAD02
struct update_game {
	uint32_t game_id;
	uint8_t status;
	uint8_t num_players;
	uint8_t max_players;
} __attribute__((packed));
//payload is the list of player_id's in the game

//The host of the game can kick a player, and a player can kick himself
#define MT_KICK_PLAYER 0xAD06
struct kick_player {
	uint32_t player_id;
} __attribute__((packed));

//A player requests to join in a game
#define MT_JOIN_GAME 0xAD07
struct join_game {
	uint32_t game_id;
} __attribute__((packed));

//A player is denied from joining the game
#define MT_REFUSE_JOIN_REQUEST 0xAD08
struct refuse_join_request {
	uint32_t player_id;
	uint16_t reason;
} __attribute__((packed));
#define GR_GAME_FULL 0x0000

#define MT_HOST_GAME 0xAD09
struct host_game {
	struct game_data;
} __attribute__((packed));




// Ignoring all gameplay packets for now


#define MAX_CHAT_LEN 256

#define MT_MAIN_CHAT 0xAE00
struct main_chat {
	uint8_t message[MAX_CHAT_LEN];
} __attribute__((packed));

#define MT_GAME_CHAT 0xAE01
struct game_chat {
	uint8_t message[MAX_CHAT_LEN];
} __attribute__((packed));

#define MT_PRIV_MESS 0xAE02
struct priv_mess {
	uint32_t player_id;
	uint8_t message[MAX_CHAT_LEN];
} __attribute__((packed));

#endif
